package com.zifeng.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zifeng.common.R;
import com.zifeng.dao.ShipDao;
import com.zifeng.dao.UserDao;
import com.zifeng.dao.UserPraiseDao;
import com.zifeng.exception.BizException;
import com.zifeng.feign.BlockFeignClient;
import com.zifeng.feign.OrderFeignClient;
import com.zifeng.pojo.*;
import com.zifeng.service.IShipService;
import com.zifeng.utils.PageUtils;
import com.zifeng.utils.RedisUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static com.zifeng.constant.RedisConstants.*;


/**
 * 船舶Controller
 * 
 * @author zifeng
 * @date 2025-03-27
 */
@RestController
@RequestMapping("/ships")
public class ShipController
{
    @Autowired
    private IShipService shipService;

    @Autowired
    private ShipDao shipDao;

    @Resource
    private OrderFeignClient orderFeignClient;

    @Autowired
    private UserDao userDao;

    @Resource
    private BlockFeignClient blockFeignClient;

    @Autowired
    private UserPraiseDao userPraiseDao;

    @Autowired
    private RedisUtils redisUtils;

    @RequestMapping("/count")
    public R count() {
        Long count = shipDao.selectCount(null);
        return R.ok().put("count", count);
    }

    @DeleteMapping("/praise/{id}")
    public R deleteUserPraise(@PathVariable("id") Long id, @RequestParam int userId) {
        Ship ship = shipService.selectShipById(id);
        ship.setPraise(ship.getPraise()-1);
        shipDao.updateById(ship);

        QueryWrapper<UserPraise> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId).eq("ship_id", id);
        userPraiseDao.delete(wrapper);
        return R.ok();
    }

    @GetMapping("/praise/list")
    public R handlePraise(@RequestParam Map<String, Object> params) {
        PageUtils page = shipService.queryPageByUuserPraise(params);
        return R.ok().put("page", page);
    }

    @Transactional
    @PostMapping("/praise/{id}")
    public R handlePraise(@PathVariable("id") Integer id, @RequestParam int userId) {
        String lock = id + "_" + userId;
        synchronized (lock) {
            QueryWrapper<UserPraise> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", userId).eq("ship_id", id);
            UserPraise userPraise = userPraiseDao.selectOne(wrapper);
            if(userPraise == null) {
                UserPraise newUserPraise = new UserPraise();
                newUserPraise.setShipId(id);
                newUserPraise.setUserId(userId);
                userPraiseDao.insert(newUserPraise);

                Ship ship = shipDao.selectById(id);
                ship.setPraise(ship.getPraise() + 1);
                shipDao.updateById(ship);
            } else {
                return R.error("您已经收藏过该船只了！");
            }
        }
        return R.ok();
    }

    @Transactional
    @PostMapping("/buyShip")
    public R buyShip(@RequestBody ShipDto shipDto) {
        try {
            shipService.buyShip(shipDto);
        }catch (BizException exception) {
            int code = exception.getCode();
            String message = exception.getMessage();
            return R.error(code, message);
        }
        return R.ok();
    }

    @RequestMapping("/listByFuzzyQuery")
    public R listByFuzzyQuery(@RequestParam Map<String, String> params) throws IOException {
        String data = params.get("data");
        if (StringUtils.isEmpty(data)) {
            return R.error(401, "查询参数不能为空");
        }
        ObjectMapper om = new ObjectMapper();
        Ship ship = om.readValue(data, Ship.class);
        List<Ship> list = shipDao.fuzzyQuery(ship);
        int currPage = Integer.parseInt(params.get("page"));
        int pageSize = Integer.parseInt(params.get("limit"));
        PageUtils page = new PageUtils(list, list.size(), pageSize, currPage);
        return R.ok().put("page", page);
    }


    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params){
        String page = (String) params.get("page");
        String size = (String) params.get("limit");
        String pageKey = SHIP_PAGE_PREFIX + page + SHIP_PAGE_SIZE_PREFIX + size;
        String shipListJson = redisUtils.getHash(pageKey, SHIP_PAGE_LIST);
        if(!shipListJson.isEmpty()) {
            List<Ship> ships = JSON.parseArray(shipListJson, Ship.class);
            Integer totalCount = Integer.valueOf(redisUtils.getHash(pageKey, SHIP_PAGE_TOTAL));
            PageUtils pageUtils = new PageUtils(ships, totalCount, Integer.valueOf(page), Integer.valueOf(size));
            return R.ok().put("page", pageUtils);
        }
        PageUtils pageUtils = shipService.queryPage(params);
        redisUtils.setHash(pageKey, SHIP_PAGE_LIST, JSON.toJSONString(pageUtils.getList()), SHIP_PAGE_TTL, TTL_TIME_UNIT);
        int totalCount = pageUtils.getTotalCount();
        redisUtils.setHash(pageKey, SHIP_PAGE_TOTAL, String.valueOf(totalCount), SHIP_PAGE_TTL, TTL_TIME_UNIT);
        return R.ok().put("page", pageUtils);
    }

    /**
     * 获取船只详细信息
     */
    @GetMapping(value = "/{id}")
    public R getShip(@PathVariable("id") Long id) {
        Ship ship = shipService.selectShipById(id);
        return R.ok().put("ship", ship);
    }

    /**
     * 新增船只
     */
    @PostMapping
    public R add(@RequestBody Ship ship) {
        shipService.insertShip(ship);
        return R.ok();
    }

    /**
     * 修改船只
     */
    @PutMapping
    public R edit(@RequestBody Ship ship)
    {
        shipService.updateShip(ship);
        return R.ok().put("ship", ship);
    }

    /**
     * 删除船只
     */
	@DeleteMapping("/{ids}")
    public R remove(@PathVariable Long[] ids)
    {
        int i = shipService.deleteShipByIds(ids);
        return R.ok();
    }
}
